#include <stdlib.h>
#include <string.h>
#include <cstdio>
#include <unistd.h>
#include <winsock2.h>
#include "network.h"
#include "tinycthread.h"
#include <tool.h>
#pragma comment(lib, "ws2_32.lib")
#define QUEUE_MAX 20
#define SERVER_MSG_HANDLER_MAX 10
struct sockaddr_in serverAddr;
SOCKET clientSocket;
char sendQueue[QUEUE_MAX][64];
int QueueBusy[QUEUE_MAX];
int sendPointer = 0;
bool clientOn = false;
//serverMsgHandler
void(*ServerMessageHandlers[SERVER_MSG_HANDLER_MAX])(const char*);
int ServerMessageHandlerCount = 0;
void(*LostConnectionHandler)() = nullptr;
int asyncSendData(void* arg);
int listenAndHandleServerData(void* args);

bool ConnectServer(char *serverAddrStr)
{
    if (clientOn)
        return false;
    // 创建TCP socket
    if ((clientSocket = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {
        printf("[C]Failed to create socket\n");
        return false;
    }
    printf("%s\n",serverAddrStr);
    char addr[64];
    char port[16];
    char *di;
    di = addr;
    bool portPart = false;
    while(*serverAddrStr) {
        if (*serverAddrStr == ':') {
            *di = 0;
            di = port;
            portPart = true;
            serverAddrStr++;
            continue;
        }
        *di = *serverAddrStr;
        di++;
        serverAddrStr++;
    }
    *di = 0;
    int intPort = atoi(port);
    printf("%s\n%s\n",addr,port);
    // 构建服务器地址
    memset(&serverAddr, 0, sizeof(serverAddr));
    serverAddr.sin_family = AF_INET;
   /// serverAddr.sin_addr.s_addr = inet_addr(serverIp);
    serverAddr.sin_port = htons(portPart ? intPort : PORT);
    //设置目标服务器
    struct hostent *hp;
    //支持域名和ip的方法
    hp = gethostbyname(addr);
    if (hp == nullptr) {
        printf("[C]Filed to DNS\n");
        return false;
    }
    memcpy(&serverAddr.sin_addr.s_addr, hp->h_addr_list[0], (size_t)hp->h_length);
    // 连接服务器
    if (connect(clientSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) {
        printf("[C]Failed to connect to server\n");
        closesocket(clientSocket);
        return false;
    }
    clientOn = true;
    thrd_t client;
    thrd_create(&client,listenAndHandleServerData, nullptr);
    return true;
}
int listenAndHandleServerData(void* args)
{
    char clientBuffer[128];
    int failReceiveCount = 0;
    int recLen = 0;
    thrd_t sender;
    thrd_create(&sender,asyncSendData, nullptr);
    while(clientOn) {
        memset(clientBuffer, 0, sizeof(clientBuffer));
        while (clientOn) {
            recLen = recv(clientSocket, clientBuffer, 128, 0);
            if(!clientOn)
                return 1;
            if (recLen == SOCKET_ERROR) {
                failReceiveCount++;
                printf("[C]Failed to receive msg from server (%d/5)\n",failReceiveCount);
                if(failReceiveCount > 4) {
                    DisconnectServer();
                    return 1;
                }
                continue;
            }
            if (recLen == 0) {
                DisconnectServer();
                return 1;
            }
            failReceiveCount = 0;
            break;
        }
        //printf("[C] <- server: %s\n", clientBuffer);
        char *tempP[ServerMessageHandlerCount];
        for (int i = 0; i < ServerMessageHandlerCount; ++i) {
            tempP[i] = clientBuffer;
            ServerMessageHandlers[i](tempP[i]);
        }
    }
    closesocket(clientSocket);
    return 0;
}
int asyncSendData(void* arg)
{
    int failCount = 0;
    //QueueBusy只能由外部填入数据后置1，由此处发完数据后置0
    //发送成功后sendPointer移动到下一位
    while(clientOn) {
        if(QueueBusy[sendPointer] != 0) { //有数据就发完再往后，没数据就往后
            //printf("[C](Q %d) -> server: %s\n",sendPointer,sendQueue[sendPointer]);
            while (clientOn && send(clientSocket, sendQueue[sendPointer], strlen(sendQueue[sendPointer]), 0) <= 0) {
                failCount++;
                printf("[C]Failed to send message to server(%d/10)\n",failCount);
                if(failCount >= 10) {
                    DisconnectServer();
                    return 1;
                }
            }
            failCount = 0;
            QueueBusy[sendPointer] = 0;
        }
        sendPointer++;
        if (sendPointer == QUEUE_MAX) {
            sendPointer = 0;
            Sleep(1);
        }

    }
    return 0;
}
void DisconnectServer(bool actively)
{
    if (!clientOn)
        return;
    clientOn = false;
    ServerMessageHandlerCount = 0;
    sendPointer = 0;
    for (int i = 0; i < QUEUE_MAX; ++i) {
        QueueBusy[i] = 0;
    }
    closesocket(clientSocket);
    if (!actively && LostConnectionHandler) // 防止回环调用
        LostConnectionHandler();
    LostConnectionHandler = nullptr;
    printf("[C]Lost connection with server.\n");
}
//队列满时返回false
bool QueueSendDataToServer(char* data)
{
    for (int i = 0; i < QUEUE_MAX; ++i) {
        if(QueueBusy[i])
            continue;
        strcpy(sendQueue[i],data);
        QueueBusy[i] = 1;
        return true;
    }
    return false;
}
bool RegisterServerMessageHandler(void(*callback)(const char*))
{
    if (ServerMessageHandlerCount == SERVER_MSG_HANDLER_MAX)
        return false;
    ServerMessageHandlers[ServerMessageHandlerCount] = callback;
    ServerMessageHandlerCount++;
    return true;
}
void SetLostConnectionHandler(void(*callback)())
{
    LostConnectionHandler = callback;
}